/*
Copyright 2014 Aaron Batilo

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

//@author: Aaron Batilo

//This LengthOrderedList will take a vector<string> and re-order it based on the length of the strings
//This is a minor efficiency change to help potentially compress data more

#include "LengthOrderedList.h"

//This vector will be ordered by the length of the strings in it, longest to shortest
vector<string> myList;

//This list is the unordered list to be passed in
vector<string> myUnorderedList;

//This constructor takes in a vector that we will re-order
LengthOrderedList::LengthOrderedList(vector<string> inUnorderedList)
{
	//Save the unordered list
	myUnorderedList = inUnorderedList;

	//Call the reorder method
	reorder();
}

LengthOrderedList::~LengthOrderedList()
{
}

//The reorder method simply goes through the unordered list
//Then it inserts each word one by one to our newly ordered list
void LengthOrderedList::reorder()
{
	//Clear any contents in our list, ensure we start fresh
	myList.clear();

	//Loop through one loop and add all of its objects to the other
	for (int i = 0; i < myUnorderedList.size(); i++)
	{
		insert(myUnorderedList[i]);
	}
}

//inline method for execution speed, there are many loops in this method
//Takes a word and will loop through the list until it can find
//the correct place to put it
inline void LengthOrderedList::insert(string inWordToAdd)
{
	//Check to see if the word we're going to add is already in the list
	if (contains(inWordToAdd))
		return;

	//Iterator to loop through the vector
	vector<string>::iterator myListIterator;

	//We'll need to store the length of the word we need to add
	int newWordSize = inWordToAdd.size();

	//Loop through the list to look for where to insert our new string
	for (int indexToInsertAt = 0; indexToInsertAt < myList.size(); indexToInsertAt++)
	{
		//This will get the size of the current word in the loop
		//This variable is mostly for readability
		int currentWordSize = myList[indexToInsertAt].size();

		//Check to see if the new word is longer
		if (newWordSize > currentWordSize)
		{
			//Set the iterator to the beginning of the vector
			myListIterator = myList.begin();
			//Insert the word at the beginning of the list
			myList.insert(myListIterator, inWordToAdd);
			//Exit the method, there's no point in going through the rest of the loop since
			//We've already added the word
			return;
		}
		else if (newWordSize == currentWordSize)
		{
			//Set the iterator to the beginning of the vector
			myListIterator = myList.begin();
			//Place the new word one index after the current word
			myList.insert(myListIterator + indexToInsertAt + 1, inWordToAdd);
			//Exit the method, there's no point in going through the rest of the loop since
			//We've already added the word
			return;
		}
		else
		{
			//End the current iteration and continue through the list
			continue;
		}
	}
	//If all else fails, this means that we just need to add the word to the end of the list
	myList.push_back(inWordToAdd);
}

//Checks to see if the list already contains the passed in word
//Again, we use inline to help execution time
inline bool LengthOrderedList::contains(string inWordToCheck)
{
	//Loop through the list
	for (int i = 0; i < myList.size(); i++)
	{
		//Look for the word in our list
		if (inWordToCheck == myList[i])
			return true;
	}
	return false;
}

//Return a word from the list
string LengthOrderedList::get(int index)
{
	return myList[index];
}